﻿using System;
using System.IO;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Xml.Serialization;
using GalaSoft.MvvmLight.Messaging;
using JustinAngel.Neurons.Framework;
using JustinAngel.Neurons.Framework.Helpers;
using JustinAngel.Neurons.Framework.Messages;
using JustinAngel.Neurons.ServerModel;
using Microsoft.Phone.Shell;
using System.Linq;

namespace JustinAngel.Neurons.Services
{
    public class DataService : IAppService, IDataService
    {

        public const string PipeUrl = "http://pipes.yahoo.com/pipes/pipe.run?_id=3677ac8a141499ae666d4a155a25a668&_render=json";

        [Dependency]
        public IWebRequestMaker WebRequestMaker { get; set; }

        [Dependency]
        public IDialogService DialogService { get; set; }

        private static RssRootItem _rssRootItem;
        public RssRootItem RssRootItem
        {
            get { return _rssRootItem; }
            set
            {
                _rssRootItem = value;
                IoC.Get<IMessenger>().Send(new RssRootItemChangedMessage(value));
            }
        }

        private string _rssWebRequestResult;

        public void StartService()
        {
            IoC.BuildUp(this);

            WebRequestMaker.StartWithCredentialsAndTimeout(PipeUrl, TimeSpan.FromSeconds(30), 
                OnSeccessfulWebRequest, 
                OnFailedWebRequest);

            IoC.Get<IMessenger>().Register<ApplicationDeactivatedMessage>(this, OnApplicationDecativated);

            IoC.Get<IMessenger>().Register<ApplicationActivatedMessage>(this, OnApplicationActivated);
        }

        private void OnApplicationActivated(ApplicationActivatedMessage obj)
        {
            if (!PhoneApplicationService.Current.State.ContainsKey("_rssWebRequestResult"))
                return;

            var data = (string)PhoneApplicationService.Current.State["_rssWebRequestResult"];
            if (string.IsNullOrEmpty(data))
                return;

            _rssWebRequestResult = data;
            SetRootItem();
        }

        private void OnApplicationDecativated(ApplicationDeactivatedMessage obj)
        {
            PhoneApplicationService.Current.State["_rssWebRequestResult"] = _rssWebRequestResult;
        }

        private void OnFailedWebRequest()
        {
            DialogService.ShowMessageBox("Something went terribly wrong. We couldn't get the list of videos to display in the app. Please open the app back up again when there's network connectivity.",
                                         "DON'T PANIC!",
                                         MessageBoxButton.OK);
            throw new ApplicationExitException();
        }

        private void OnSeccessfulWebRequest(Stream resultStream)
        {
            _rssWebRequestResult = resultStream.ReadToEnd();

            SetRootItem();
        }

        private void SetRootItem()
        {
            RssRootItem = DeserializeStreamToBusinessObject(_rssWebRequestResult);
        }

        public static RssRootItem DeserializeStreamToBusinessObject(string rssWebRequestResult)
        {
            var knownTypes =
                typeof(DataService).Assembly.GetTypes().Where(t => t.GetCustomAttributes(typeof (KnownTypeAttribute), false).Any());
            var serializer = new DataContractJsonSerializer(typeof(RssRootItem), knownTypes);

            return (RssRootItem)serializer.ReadObject(rssWebRequestResult.ToStream());
        }

        public void StopService()
        {
        }

        public void WithRootRssItem(Action<RssRootItem> action)
        {
            if (RssRootItem != null)
            {
                action(RssRootItem);
            }
            else
            {
                IoC.Get<IMessenger>().Register<RssRootItemChangedMessage>(this,
                    msg => action(msg.Content));
            }
        }
    }
}
